/**
 * 索引类型指的不是某一个特定的类型工具，
 * 它其实包含三个部分：索引签名类型、索引类型查询 与 索引类型访问，这三者都是独立的类型工具。
 * 唯一共同点是，它们都通过索引的形式来进行类型操作，
 * 其中，索引签名类型 是声明，
 * 索引类型查询 与 索引类型访问 两者则是读取。
*/

/**
 * 索引类型访问：
 * 其访问方式与返回值均是类型
 * 索引类型查询的本质其实就是，通过 键的字面量类型 访问这个 键对应的键值类型
 * 
 * 在 JavaScript 中可以通过 obj[expression] 的方式来动态访问一个对象属性（即计算属性），
 * expression 表达式会先被执行，然后使用返回值来访问属性。
 * 而 TypeScript 中也可以通过类似的方式，只不过这里的 expression 要换成类型：
*/
interface NumberRecord {
    propA: number;
    propB: boolean;
    [key: string]: number | boolean;
}
type PropType = NumberRecord[string]; // number

//通过结合 索引类型查询keyof 一次性获取 接口所有的 键值的字面量类型
interface Foo {
    propA: number | string;
    propB: boolean;
}
type PropTypeUnion = Foo[keyof Foo]; // string | number | boolean
const test: PropTypeUnion = "hanxuming"

//注意，在未声明 索引签名类型 的情况下，不能使用 NumberRecord[string] 这种原始类型的访问方式，
//而只能通过 键名的字面量类型 来进行访问。
interface FooA {
    propA: number;
}
type PropAType = FooA[string];
type PropBType = FooA["propA"];

//export {}：解决“无法重新声明块范围变量”错误提示问题
export { }